#ifndef PLUGINHANDLER_H
#define PLUGINHANDLER_H

#include "stdafx.h"
#include <dlfcn.h>

namespace Core {
    template <class T> class PluginHandler
    {
        public:
            PluginHandler() {
                handle = NULL;
                instance = NULL;
            }

            virtual ~PluginHandler() {

            }

            void Open(std::string pPluginFile) {
                handle = dlopen(pPluginFile.c_str() , RTLD_LAZY);
                if (!handle) {
                    //std::cout << "Failed" << std::endl;
                    throw exception();
                }
                else {
                    //std::cout << "Success" << std::endl;
                }
            }

            void Load() {
                if (handle != NULL) {
                    typedef T* create_t();

                    create_t* create = (create_t*) dlsym(handle , "create");
                    if (create != NULL) {
                        instance = create();
                    }
                    else {
                        throw exception();
                    }
                }
            }

            T* GetInstance() {
                return instance;
            }

            void Close() {
                if (handle != NULL)
                    dlclose(handle);
            }

            void Unload() {
                if (handle != NULL) {
                    typedef void destroy_t(T*);
                    destroy_t *destroy = (destroy_t*) dlsym(handle , "destroy");
                    if (destroy != NULL) {
                        destroy(instance);
                    }
                    else {
                        throw exception();
                    }
                }
            }

        protected:
        private:
            T* instance;
            void* handle;

    };


}

#endif // PLUGINHANDLER_H
